package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"my_go_open/utils"
	"strconv"
	"time"
)

/*
// 测试用数据表结构
CREATE TABLE `mysql`.`my_test` (
	`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
	`a` VARCHAR(50) NOT NULL DEFAULT '',
	`b` INT(10) NOT NULL DEFAULT '0',
	PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB
*/
func main() {
	m, err := utils.NewModel("my_test", "id", "db_a")
	if err != nil {
		println(err.Error())
		return
	}
	// m.SetMasterAsSlave(true) // 主库当从库用

	// 结束时关闭连接（业务中不用这样做）
	// defer m.CloseDB()

	// 插入一条
	newId, _ := m.Insert(&utils.ModelItem{
		"A": utils.StrRandom(4, ""),
		"B": utils.RandInt(10000),
	}, true)
	println("[" + utils.TimeNowNice() + "] inserted one, get new id: " + strconv.FormatInt(newId, 10))

	// 更新刚插入的数据
	update1, _ := m.UpdateById(&utils.ModelItem{
		"A": "inserted just now",
		"B": "9999",
	}, strconv.FormatInt(newId, 10))
	println("[" + utils.TimeNowNice() + "] updated one : " + strconv.FormatInt(update1, 10))

	// 插入批量，一次5条数据
	okCnt, _ := m.InsertBatch([]*utils.ModelItem{
		{
			"A": utils.StrRandom(4, ""),
			"B": utils.RandInt(10000),
		},
		{
			"A": utils.StrRandom(4, ""),
			"B": utils.RandInt(10000),
		},
		{
			"A": utils.StrRandom(4, ""),
			"B": utils.RandInt(10000),
		},
		{
			"A": utils.StrRandom(4, ""),
			"B": utils.RandInt(10000),
		},
		{
			"A": utils.StrRandom(4, ""),
			"B": utils.RandInt(10000),
		},
	})
	println("[" + utils.TimeNowNice() + "] inserted batch items: " + strconv.FormatInt(okCnt, 10))

	// 按ID取一条数据
	data1, _ := m.GetById(strconv.FormatInt(newId, 10))
	data1json, _ := json.Marshal(data1)
	println("[" + utils.TimeNowNice() + "] got one : " + string(data1json))

	// 按多个ID取数据
	data2, _ := m.GetByIds([]interface{}{
		strconv.FormatInt(newId, 10),
		"2",
		"3",
		"4",
		"5",
		"6",
	}, "id", "a")
	data2json, _ := json.Marshal(data2)
	println("[" + utils.TimeNowNice() + "] got ids : " + string(data2json))

	// 统计条数
	cnt, _ := m.Count("select count(*) from my_test where b < ?", 2000)
	println("[" + utils.TimeNowNice() + "] select count : " + strconv.FormatInt(cnt, 10))

	// 更新数据
	uc, _ := m.Update("update my_test set a = ?, b = ? where b < ?", "updated", 2001, 2000)
	println("[" + utils.TimeNowNice() + "] updated : " + strconv.FormatInt(uc, 10))

	// 按ID删除一条或多条数据
	dc1, _ := m.DelByIds(strconv.FormatInt(newId, 10))
	// m.CloseQueryLog() // 关闭日志记录
	dc2, _ := m.DelByIds("8", "9", "10")
	println("[" + utils.TimeNowNice() + "] deleted : " + strconv.FormatInt(dc1+dc2, 10))

	// 执行事务
	err = m.Transaction(func(tx *sql.Tx, logger *utils.Queue) error {
		query := "delete from my_test where b >= ?"
		params := []interface{}{2000}
		go func() {
			logger.Push(&utils.QueryLog{
				Query:  query,
				When:   utils.TimeNowNice(),
				Params: params,
			})
		}()
		_, err = tx.Exec(query, params...)
		if err != nil {
			return err
		}
		query = "update my_test set a = ?, b = ? where b < ?"
		params = []interface{}{"more than 1000", 1000, 1000}
		go func() {
			logger.Push(&utils.QueryLog{
				Query:  query,
				When:   utils.TimeNowNice(),
				Params: params,
			})
		}()
		_, err = tx.Exec(query, params...)
		if err != nil {
			return err
		}
		return nil
	})
	msg := "ok"
	if err != nil {
		msg = err.Error()
	}
	println("[" + utils.TimeNowNice() + "] transaction msg : " + msg)

	// SQL日志
	logs := m.GetQueryLogs()
	for _, log := range logs {
		println("-----------------")
		fmt.Printf("When: %s\nQuery: %s;\nParams: %v\nErr: %v\n", log.When, log.Query, log.Params, log.Err)
	}

	for {
		time.Sleep(3 * time.Second)
		for i := 0; i < 20; i++ {
			go func(i int) {
				tn, err := m.Select("select now()")
				if err != nil {
					println("error : ~~~~~~ \n" + err.Error())
				} else {
					data2json, _ = json.Marshal(tn)
					println(i, string(data2json), utils.GetSqlOpenCnt())
				}
			}(i)
		}
	}
}
